#include "src/scene/pointLight.h"

#include <iostream>

#include "src/scene/hbb/box.h"
#include "src/scene/object.h"
#include "src/scene/material.h"
#include "src/defines/functions.h"

PointLight::PointLight() : Light() {
    id = 0;
	position = Vector3D(5.0, -10.0, 10.0);
}

PointLight::PointLight(unsigned int _id, const Vector3D &_pos, const Color &_c, double _e)
    : Light(_id, _c, _e), position(_pos){
}

PointLight::~PointLight(){
}

Color PointLight::getIntersectionColor(const NearestInfo &_nearest, const Vector3D &_view, HBBTree *_tree, const unsigned int &_attenuation) const
{
    Vector3D toLight = position - _nearest.point;
    Vector3D toLightNormalized = toLight.normalize();

    if(isOccluded(_nearest, toLightNormalized, _tree, position))
        return Color(0.0, 0.0, 0.0, 0.0);

    double cosI = _nearest.normal.dotProduct(toLightNormalized);

    Vector3D reflected = (_nearest.normal * (2 * cosI)) - toLightNormalized;

    Material material = _nearest.object->getMaterial();
    Color materialDiffuse =  material.diffuse;
    Color materialSpecular =  material.specular;

    if(material.useTexture() && (material.texture->coloringType == REPLACE))
    {
        materialDiffuse = _nearest.texture;
        materialSpecular = _nearest.texture;
    }

    Color diffuse (0,0,0,0), specular(0,0,0,0);
    double diffuseDot = _nearest.normal.dotProduct( toLightNormalized );
    if(diffuseDot > 0)
        diffuse = materialDiffuse * ( material.kd * diffuseDot);

    double specularDot = reflected.normalize().dotProduct(_view);
    if(specularDot > 0)
        specular = materialSpecular * ( material.ks * ( pow( specularDot , material.specularPower) ) );

    Color result = color * (diffuse + specular);

    return result;// * attenuation(_attenuation, distance); //a cor vezes a atenuação;
}

void PointLight::shine(const GLenum &num)
{
    GLfloat position__[3];
    GLfloat color__[4];
    glLightfv(num, GL_POSITION, position.toGL(position__));
    glLightfv(num, GL_AMBIENT, color.toGL(color__));
    glLightfv(num, GL_DIFFUSE,  color__);
    glLightfv(num, GL_SPECULAR, color__);
//
//    position.print();
//    std::cout << "position__" << position__[0] << " " << position__[1] << " "<< position__[2] <<std::endl;
//    int nhe;
//    std::cin >> nhe;

    glEnable(num);
}

void PointLight::draw() const
{
	glPushMatrix();

	glTranslated(position.x, position.y, position.z);

	glEnable(GL_COLOR_MATERIAL);
	glDisable(GL_LIGHTING);


    glPointSize(10);

    if(selected) glColor3d(1, 0, 0);
    else glColor4d(color.red, color.green, color.blue, color.alpha);

    glBegin(GL_POINTS);
        glVertex3d(0, 0, 0);
    glEnd();
    glPointSize(1);
    glEnable(GL_LIGHTING);

    glDisable(GL_COLOR_MATERIAL);


	glPopMatrix();
}

//void PointLight::calculateProjectionMap(HBBTree *_tree)
//{
//
//}

void PointLight::generatePhotonPointDirection(Vector3D *_pos, Vector3D *_dir, Object *_object) const
{
    //a posição é a posição da luz
    *_pos = position;


    if(_object)
    {
        *_dir = objectMap(*_pos, _object);
    }
    else
    {
        double phi = (rand()%18001)/100.0;//vertical [0,180]
        double theta = (rand()%36000)/100.0;//horizontal [0, 360)

        //a direção é de acordo com uma esfera
        *_dir = Functions::sphericalCoordinates(phi, theta);

    }

    //se fizer o mapa de projeção, essa direção irá depender dele
}
